package com.t3.anistory
{
	import com.t3.display.Thumbnail;
	import com.t3.events.DragEvent;
	import com.t3.fx.DropArea;
	import com.t3.fx.Letter;
	import com.t3.util.ArrayUtil;
	import flash.geom.Point;
	import flash.utils.Dictionary;	
	
	import flash.display.DisplayObject;
	import flash.display.Shape;
	import flash.geom.Rectangle;

	/**
	 * Notebook
	 * Deze klasse is de schrijfkant van de applicatie, hij houdt de letters bij
	 * en zorgt ervoor dat deze zichtbaar worden op een bepaald oppervlakte
	 * @author David Hoevers, Veron Wormeester 
	 **/
	public class Notebook extends DropArea
	{
		private var _thumb:Thumbnail;
		private var _hitObject:Shape = new Shape();
		private var xoff:uint = 0;
		
		public function Notebook( bounds:Rectangle ):void 
		{
			super( bounds, Letter, 0xFFFFFF, 0 );
			
			_thumb = new Thumbnail( bounds, this, 1/8, true, true, true );
			
			addChild( _hitObject );
		}
		
		protected override function repaint():void
		{
			this._hitObject.graphics.beginFill( 0xFFFFFF, 0 );
			this._hitObject.graphics.drawRect( 0, 0, _bounds.width, _bounds.height );
			this._hitObject.graphics.endFill();
		}
		
		public function get thumbnail():Thumbnail
		{
			return _thumb;
		}
		
		/**
		 * addLetter
		 * Voegt een letter toe, elk letter heeft zijn eigen ID, welke vervolgens in een dictionary wordt bewaard
		 */
		private function addLetter( letter:Letter ) : void
		{
			this.addChild(letter);
			_objects[ letter.id ] = letter;
		}
		
		/**
		 * sketchLetters
		 * Deze "tekent" de letters die hij gekregen heeft uit een opgeslagen object, omdat deze letters niet
		 * Alle eigenschappen mee hebben genomen in het opslaan, worden deze alseerst opnieuw geconstrueerd uit 
		 * de gegevens die wel opgeslagen zijn, dat is de letter en de x en y positie. 
		 */
		public function sketchLetters( letters:Object ) : void 
		{
			for ( var a:uint = 0; a < letters.length; a++ )
			{
				var letter:Letter = new Letter(letters[a].letter, "clone", 48);
				addLetter(letter);
				letter.stageLoc = new Point(letters[a].savedX, letters[a].savedY);
			}
		}
		
		private function removeLetter( letter:Letter ) : void 
		{
			if( contains( letter ) )
			{
				removeChild( letter );
			}
			
			letter.removeEventListener( DragEvent.OBJECT_DROPPED, objectDropped );
			letter.removeEventListener( DragEvent.OBJECT_REMOVED, objectRemoved );
			
			_objects[ letter.id ] = null;
			delete( _objects[ letter.id ] ); 
		}
		
		/**
		 * objectDropped
		 * Deze functie kijkt of de letter op de plek, waar deze gedropt is, goed staat en anders snapt 
		 * hij deze op een plek waar hij wel mag bestaan
		 * TODO: letter kan nu nog op sketchbook komen als er teveel letters achter elkaar worden gesnapt.
		 */
		public override function objectDropped( event:DragEvent ):void
		{
			if( event.target is Letter )
			{
				var letter:Letter = event.target as Letter;
			
				letter.dragState.dropOrigin = this;
				
			
				xoff = 0;
				var yoff:int = 4;
				var dist:uint = this.height / 11;
				var xdist:uint = checkSpot( letter, new Point( letter.stageX + xoff, letter.stageY - ( letter.stageY - this.stageY ) % dist + yoff ) ) 
											
				addLetter( letter );
				
				letter.snapTo( letter.stageX + xdist, letter.stageY - ( letter.stageY - this.stageY ) % dist + yoff );

			
			}
		}
		
		/** 
		 * checkSpot --- Testfunctie voor hittest op letters
		 * Deze functie doorloopt alle letters en kijkt of hij niet raakt met een bepaalde letter.
		 * Omdat er een tween op de snapfunctie zit wordt er gekeken met het Point waar hij naar toe snapt, omdat deze soms kan missen
		 * Is er ook een eenmalige check gedaan op een object hittest, dit geeft meer zekerheid dat deze werkt 
		 */
		public function checkSpot( letter:Letter, point:Point ):uint
		{
			var yoff:int = 4;
			var dist:uint = this.height / 11;
			
			var letters:Array = ArrayUtil.dictToArray(_objects);
			
			for ( var a:uint = 0; a < letters.length; a++ )
			{
				if (letters[a].hitObject.hitTestPoint( point.x, point.y ) && letters[a] != letter)
				{
					xoff += 2;
					checkSpot( letter, new Point( letter.stageX + xoff, letter.stageY - ( letter.stageY - this.stageY ) % dist + yoff ) );
					break;
				}
			}
			
			for ( var b:uint = 0; b < letters.length; b++ )
			{
				if (letters[b] != letter && letters[b].hitObject.hitTestObject( letter.hitObject ) && xoff == 0 )
				{
					xoff += 2;
					checkSpot( letter, new Point( letter.stageX + xoff, letter.stageY - ( letter.stageY - this.stageY ) % dist + yoff ) );
				}
			}
				
			return xoff;
		}
		
		public override function objectRemoved( event:DragEvent ):void
		{
			if( event.target is Letter )
			{
				removeLetter( event.target as Letter );
			}
		}
		
		public override function get hitObject():DisplayObject
		{
			return _hitObject;
		}
	}
}
